#include <stdio.h>
#include "weed.h"
int weedErrorCount = 0;
int warningcount = 0;
int returnsInMain = 0;
int weed_body_root(BODY *root) {
	weed_decl_list(root->decl_list);
	weed_root_statement_list(root->statement_list);
	if(returnsInMain>0){
		weedErrorCount++;
	}
	return weedErrorCount;
}
void weed_root_statement_list(STATEMENT_LIST *statement_list){
	switch(statement_list->kind){
	case statement_list_baseK:
		weed_root_statement(statement_list->statement);
		break;
	case statement_listK:
		weed_root_statement_list(statement_list->statement_list);
		weed_root_statement(statement_list->statement);
		break;
	}
}
void weed_root_statement(STATEMENT *statement){
	if(statement->kind == returnK){
		fprintf(stderr,"Error:%d: return statement found in main scope\n", statement->lineno);
		returnsInMain++;
	}
	if(statement->kind == ifK){
		weed_root_statement(statement->val.ifE.statement);
		OPT_ELSE *opt_else;
		opt_else = statement->val.ifE.opt_else;
		if(opt_else!=0){
			weed_root_statement(opt_else->statement);
		}
	}
	if(statement->kind == whileK){
		weed_root_statement(statement->val.whileE.statement);
	}
	if(statement->kind == statementlistK){
		weed_root_statement_list(statement->val.statement_list);
	}
}
void weed_decl_list(DECL_LIST *decl_list){
	if(decl_list!=0){
		weed_decl_list(decl_list->decl_list);
		weed_declaration(decl_list->declaration);
	}
}
void weed_declaration(DECLARATION *declaration){
	if(declaration->kind == funcK){
		weed_function(declaration->val.function);
	}
}
void weed_function(FUNCTION *function){
	BODY *body;
	body = function->body;
	weed_decl_list(body->decl_list);
	if(weed_statement_list(body->statement_list)==1){
		weedErrorCount++;
		HEAD *head;
		head = function->head;
		fprintf(stderr, "Error:%d: function '%s' missing return statement\n",head->lineno, head->id);
	}
	warningcount=0;
}
int weed_statement_list(STATEMENT_LIST *statement_list){
	switch(statement_list->kind){
	case statement_list_baseK:
		return weed_statement(statement_list->statement);
		break;
	case statement_listK:
		if(weed_statement_list(statement_list->statement_list)==0){
			if(warningcount==0){
				fprintf(stderr,"Warning:%d: Dead code after return statement ignored\n",statement_list->lineno);
			}
			statement_list->statement = NULL;
			warningcount++;
			return 0;
		}
		return weed_statement(statement_list->statement);
		break;
	}
	return 1;
}
int weed_statement(STATEMENT *statement){
	if(statement->kind == returnK){
		return 0;
	}
	if(statement->kind == ifK){
		if(statement->val.ifE.opt_else!=0){
			OPT_ELSE *opt_else;
			opt_else = statement->val.ifE.opt_else;
			if(weed_statement(statement->val.ifE.statement)==0 && weed_statement(opt_else->statement)==0){
				return 0;
			}
		}
	}
	if(statement->kind == statementlistK){
		return weed_statement_list(statement->val.statement_list);
	}
	return 1;
}
